"""
配置加载模块
支持YAML配置文件加载，环境变量覆盖，敏感信息加密
"""
import os
import yaml
from pathlib import Path
from typing import Any, Dict
from cryptography.fernet import Fernet
from dotenv import load_dotenv


class ConfigLoader:
    """配置加载器"""
    
    def __init__(self, config_dir: str = "config", env: str = None):
        """
        初始化配置加载器
        
        参数:
            config_dir: 配置文件目录
            env: 环境（development/testing/production）
        """
        self.config_dir = Path(config_dir)
        self.env = env or os.getenv("TRADING_ENV", "development")
        self.config = {}
        self.cipher_suite = None
        
        # 加载环境变量
        load_dotenv()
        
        # 初始化加密
        self._init_encryption()
        
        # 加载配置
        self._load_config()
    
    def _init_encryption(self):
        """初始化加密套件"""
        # 从环境变量获取加密密钥，如果不存在则生成新密钥
        encryption_key = os.getenv("ENCRYPTION_KEY")
        if not encryption_key:
            encryption_key = Fernet.generate_key().decode()
            print(f"警告：未设置ENCRYPTION_KEY环境变量，已生成新密钥：{encryption_key}")
            print("请将此密钥保存到.env文件中：ENCRYPTION_KEY={encryption_key}")
        
        self.cipher_suite = Fernet(encryption_key.encode() if isinstance(encryption_key, str) else encryption_key)
    
    def _load_config(self):
        """加载配置文件"""
        # 加载主配置文件
        main_config_file = self.config_dir / "config.yaml"
        if main_config_file.exists():
            with open(main_config_file, 'r', encoding='utf-8') as f:
                self.config = yaml.safe_load(f) or {}
        
        # 加载环境特定配置
        env_config_file = self.config_dir / f"config.{self.env}.yaml"
        if env_config_file.exists():
            with open(env_config_file, 'r', encoding='utf-8') as f:
                env_config = yaml.safe_load(f) or {}
                self._merge_config(self.config, env_config)
        
        # 加载策略配置
        strategies_config_file = self.config_dir / "strategies.yaml"
        if strategies_config_file.exists():
            with open(strategies_config_file, 'r', encoding='utf-8') as f:
                self.config['strategies'] = yaml.safe_load(f) or {}
        
        # 加载风险配置
        risk_config_file = self.config_dir / "risk.yaml"
        if risk_config_file.exists():
            with open(risk_config_file, 'r', encoding='utf-8') as f:
                self.config['risk'] = yaml.safe_load(f) or {}
        
        # 环境变量覆盖
        self._override_from_env()
    
    def _merge_config(self, base: Dict, override: Dict):
        """
        合并配置字典
        
        参数:
            base: 基础配置
            override: 覆盖配置
        """
        for key, value in override.items():
            if key in base and isinstance(base[key], dict) and isinstance(value, dict):
                self._merge_config(base[key], value)
            else:
                base[key] = value
    
    def _override_from_env(self):
        """从环境变量覆盖配置"""
        # OKX API配置
        if os.getenv("OKX_API_KEY"):
            self.config.setdefault('exchange', {}).setdefault('okx', {})['api_key'] = os.getenv("OKX_API_KEY")
        if os.getenv("OKX_SECRET_KEY"):
            self.config.setdefault('exchange', {}).setdefault('okx', {})['secret_key'] = os.getenv("OKX_SECRET_KEY")
        if os.getenv("OKX_PASSPHRASE"):
            self.config.setdefault('exchange', {}).setdefault('okx', {})['passphrase'] = os.getenv("OKX_PASSPHRASE")
        
        # 数据库配置
        if os.getenv("DATABASE_URL"):
            self.config.setdefault('database', {})['url'] = os.getenv("DATABASE_URL")
        
        # Redis配置
        if os.getenv("REDIS_URL"):
            self.config.setdefault('redis', {})['url'] = os.getenv("REDIS_URL")
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        获取配置值（支持点号分隔的嵌套键）
        
        参数:
            key: 配置键（如 'exchange.okx.api_key'）
            default: 默认值
            
        返回:
            配置值
        """
        keys = key.split('.')
        value = self.config
        
        for k in keys:
            if isinstance(value, dict):
                value = value.get(k)
                if value is None:
                    return default
            else:
                return default
        
        return value
    
    def set(self, key: str, value: Any):
        """
        设置配置值
        
        参数:
            key: 配置键
            value: 配置值
        """
        keys = key.split('.')
        config = self.config
        
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        
        config[keys[-1]] = value
    
    def encrypt(self, plaintext: str) -> str:
        """
        加密字符串
        
        参数:
            plaintext: 明文
            
        返回:
            密文
        """
        return self.cipher_suite.encrypt(plaintext.encode()).decode()
    
    def decrypt(self, ciphertext: str) -> str:
        """
        解密字符串
        
        参数:
            ciphertext: 密文
            
        返回:
            明文
        """
        return self.cipher_suite.decrypt(ciphertext.encode()).decode()
    
    def get_exchange_config(self, exchange: str = 'okx') -> Dict:
        """
        获取交易所配置
        
        参数:
            exchange: 交易所名称
            
        返回:
            交易所配置字典
        """
        return self.get(f'exchange.{exchange}', {})
    
    def get_strategy_config(self, strategy_name: str) -> Dict:
        """
        获取策略配置
        
        参数:
            strategy_name: 策略名称
            
        返回:
            策略配置字典
        """
        return self.get(f'strategies.{strategy_name}', {})
    
    def get_risk_config(self) -> Dict:
        """
        获取风险配置
        
        返回:
            风险配置字典
        """
        return self.get('risk', {})
    
    def save_config(self, filename: str = None):
        """
        保存配置到文件
        
        参数:
            filename: 文件名（不含路径）
        """
        if filename is None:
            filename = f"config.{self.env}.yaml"
        
        config_file = self.config_dir / filename
        with open(config_file, 'w', encoding='utf-8') as f:
            yaml.dump(self.config, f, allow_unicode=True, default_flow_style=False)
    
    def __repr__(self):
        return f"ConfigLoader(env={self.env}, config_dir={self.config_dir})"


# 创建全局配置实例
config = ConfigLoader()


if __name__ == "__main__":
    # 测试配置加载
    print("当前环境:", config.env)
    print("配置目录:", config.config_dir)
    
    # 测试获取配置
    print("\n交易所配置:")
    print(config.get_exchange_config('okx'))
    
    # 测试加密解密
    print("\n加密测试:")
    original = "my_secret_api_key_123456"
    encrypted = config.encrypt(original)
    decrypted = config.decrypt(encrypted)
    print(f"原文: {original}")
    print(f"密文: {encrypted}")
    print(f"解密: {decrypted}")
    print(f"加密解密成功: {original == decrypted}")
